int cpu = smp_processor_id();
struct ac_timer *t, **heap;
s_time_t now;
+ void (*fn)(unsigned long);
spin_lock_irq(&ac_timers[cpu].lock);
((t = heap[1])->expires < (now + TIMER_SLOP)) )
{
remove_entry(heap, t);
-
- spin_unlock_irq(&ac_timers[cpu].lock);
- if ( t->function != NULL )
- t->function(t->data);
- spin_lock_irq(&ac_timers[cpu].lock);
-
+
+ if ( (fn = t->function) != NULL )
+ {
+ unsigned long data = t->data;
+ spin_unlock_irq(&ac_timers[cpu].lock);
+ (*fn)(data);
+ spin_lock_irq(&ac_timers[cpu].lock);
+ }
+
/* Heap may have grown while the lock was released. */
heap = ac_timers[cpu].heap;
}
spin_lock_init(&schedule_data[i].lock);
schedule_data[i].curr = &idle0_task;
- init_ac_timer(&schedule_data[i].s_timer, i);
+ init_ac_timer(&schedule_data[i].s_timer);
+ schedule_data[i].s_timer.cpu = i;
schedule_data[i].s_timer.data = 2;
schedule_data[i].s_timer.function = &sched_timer;
- init_ac_timer(&fallback_timer[i], i);
+ init_ac_timer(&fallback_timer[i]);
+ fallback_timer[i].cpu = i;
fallback_timer[i].data = 0;
fallback_timer[i].function = &fallback_timer_fn;
}
schedule_data[0].idle = &idle0_task;
- init_ac_timer(&v_timer, 0);
+ init_ac_timer(&v_timer);
+ v_timer.cpu = 0;
v_timer.data = 0;
v_timer.function = &virt_timer;
}
#ifndef _AC_TIMER_H_
#define _AC_TIMER_H_
-#include <xeno/time.h> /* include notion of time */
-
-/*
- * The Xen Hypervisor provides two types of timers:
- *
- * - Linux style, jiffy based timers for legacy code and coarse grain timeouts
- * These are defined in ./include/xeno/timer.h and implemented in
- * ./common/timer.c. Unlike in Linux they are executed not on a periodic
- * timer interrupt but "occasionally" with somewhat lesser accuracy.
- *
- * - accurate timers defined in this file and implemented in
- * ./common/ac_timer.c. These are implemented using a programmable timer
- * interrupt and are thus as accurate as the hardware allows. Where possible
- * we use the local APIC for this purpose. However, this fact is hidden
- * behind a architecture independent layer.
- * accurate timers are programmed using system time.
- *
- * The interface to accurate timers is very similar to Linux timers with the
- * exception that the expires value is not expressed in jiffies but in ns from
- * boot time. Its implementation however, is entirely different.
- */
+#include <xeno/time.h>
struct ac_timer {
- s_time_t expires; /* system time time out value */
+ /*
+ * PUBLIC FIELDS
+ */
+ /* System time expiry value (nanoseconds since boot). */
+ s_time_t expires;
+ /* CPU on which this timer will be installed and executed. */
+ unsigned int cpu;
+ /* On expiry, '(*function)(data)' will be executed in softirq context. */
unsigned long data;
void (*function)(unsigned long);
- unsigned int cpu;
+
+ /*
+ * PRIVATE FIELDS
+ */
unsigned int heap_offset;
};
-/* interface for "clients" */
-extern void add_ac_timer(struct ac_timer *timer);
-extern void rem_ac_timer(struct ac_timer *timer);
-extern void mod_ac_timer(struct ac_timer *timer, s_time_t new_time);
-static __inline__ void init_ac_timer(struct ac_timer *timer, int cpu)
+/*
+ * This function can be called for any CPU from any CPU in any context.
+ * It initialises the private fields of the ac_timer structure.
+ */
+static __inline__ void init_ac_timer(struct ac_timer *timer)
{
- timer->cpu = cpu;
timer->heap_offset = 0;
}
-/* check if ac_timer is active, i.e., on the list */
+
+/*
+ * This function can be called for any CPU from any CPU in any context.
+ * It returns TRUE if the given timer is on a timer list.
+ */
static __inline__ int active_ac_timer(struct ac_timer *timer)
{
return (timer->heap_offset != 0);
}
-/* interface used by programmable timer, implemented hardware dependent */
-extern int reprogram_ac_timer(s_time_t timeout);
+/*
+ * This function can be called for any CPU from any CPU in any context, BUT:
+ * -- The private fields must have been initialised (ac_timer_init).
+ * -- All public fields must be initialised.
+ * -- The timer must not currently be on a timer list.
+ */
+extern void add_ac_timer(struct ac_timer *timer);
+
+/*
+ * This function can be called for any CPU from any CPU in any context, BUT:
+ * -- The private fields must have been initialised (ac_timer_init).
+ * -- All public fields must be initialised.
+ * -- The timer must currently be on a timer list.
+ */
+extern void rem_ac_timer(struct ac_timer *timer);
+
+/*
+ * This function can be called for any CPU from any CPU in any context, BUT:
+ * -- The private fields must have been initialised (ac_timer_init).
+ * -- All public fields must be initialised.
+ */
+extern void mod_ac_timer(struct ac_timer *timer, s_time_t new_time);
+
+
+/*
+ * PRIVATE DEFINITIONS
+ */
+
+extern int reprogram_ac_timer(s_time_t timeout);
#endif /* _AC_TIMER_H_ */